package com.dream.xcarrecorder;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.util.Size;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import com.dream.libxrec.camera.CameraPreviewHelper;
import com.dream.libxrec.camera.ICamera;
import com.dream.libxrec.encode.audio.AACEncoder;
import com.dream.libxrec.encode.audio.AMREncoder;
import com.dream.libxrec.encode.audio.IAudioEncoder;
import com.dream.libxrec.rec.Mp4RecordHelper;
import com.dream.libxrec.encode.video.H264Encoder;
import com.dream.libxrec.encode.video.IVideoEncoder;
import com.dream.libxrec.sound.XAudioRecord;
import com.dream.libxrec.sound.ISoundRec;
import com.dream.libxrec.utils.ImageUtils;
import com.dream.libxrec.utils.OsdHelper;
import com.luoye.bzyuvlib.BZYUVUtil;

import java.io.File;

public class MainActivity extends Activity implements View.OnClickListener{
    private Context mContext;

    private Mp4RecordHelper mHelper = null;//录制工具类
    private ICamera mCamera = null;//相机
    private ISoundRec mSoundRec = null;//录音机
    private IVideoEncoder mVideoEncoder = null;//视频编码器
    private IAudioEncoder mAudioEncoder = null;//音频编码器

    private ImageView mPicIV;
    private Button mBtnCamera,mBtnStartRec,
            mBtnStopRec,mBtnSoundRec,mBtnTakPic,mBtnPreview;

    private SurfaceView mSurfaceView;
    private CameraPreviewHelper mPreviewHelper = null;//预览工具类

    private final OsdHelper mOsdHelper = new OsdHelper(5,5);

    private boolean isTakePic;//是否拍照

    private static final int SOUND_SAMPLE = 16000;//音频采样率
    private static final int SOUND_CHANNEL = 1;//音频通道数
    private static final int SOUND_BITRATE = 16000;//音频码率

    private final ICamera.ImageAvailableListener mImageAvailableListener = new ICamera.ImageAvailableListener() {
        @Override
        public void onImageAvailable(String channel,byte[] data,
                                     int type,
                                     int width, int height) {
            if (type != ICamera.TYPE_I420){
                return;
            }

            boolean isRec =
                    mVideoEncoder != null&&mVideoEncoder.isRun();

            //添加水印
            mOsdHelper.addYuvOsdText(data,width,height,
                    "CH "+channel+",状态:"+(isRec?"录制中":"空闲中"),20,20);

            if (isTakePic){
                isTakePic = false;
                byte[] nv21 = new byte[data.length];
                BZYUVUtil.yuvI420ToNV21(data,nv21,width,height);
                takePicture(nv21,width,height);
            }

            if (mPreviewHelper != null){
                mPreviewHelper.draw(data,false,0);
            }

            if (isRec){
                byte[] nv12 = new byte[data.length];
                BZYUVUtil.yuvI420ToNV12(data,nv12,width,height);
                mVideoEncoder.encode(nv12,0,nv12.length);
            }
        }
    };

    private final ISoundRec.ISoundRecListener mSoundRecListener =
            new ISoundRec.ISoundRecListener(){

                @Override
                public void onSoundRec(byte[] pcm, int size) {
                    if (mAudioEncoder != null&&mAudioEncoder.isRun()){
                        mAudioEncoder.encode(pcm,0,size);
                    }
                }
            };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        initView();
        checkPermission();
        Log.i("Test","Version1");
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
//            if (!Environment.isExternalStorageManager()){
//                Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
//                intent.setData(Uri.parse("package:" + getPackageName()));
//                startActivityForResult(intent, 1);
//            }
//        }
    }

    private void takePicture(byte[] data, int width, int height) {
        Bitmap bitmap = ImageUtils.nv21toBitmap(data,width,height,60);

        runOnUiThread(()->{
            mPicIV.setImageBitmap(bitmap);
            mPicIV.setVisibility(View.VISIBLE);
        });
    }

    private void checkPermission(){
        boolean isGrantedCamera = ActivityCompat.checkSelfPermission(this,
                Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED;
        boolean isGrantedAudioRecord =  ActivityCompat.checkSelfPermission(this,
                Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED;

        if (isGrantedCamera||isGrantedAudioRecord){
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.CAMERA,
                            Manifest.permission.RECORD_AUDIO
                    },0);
        }
    }

    private void initView() {
        mSurfaceView = findViewById(R.id.main_sv_preview);
        mPicIV = findViewById(R.id.main_img_pic);
        mPicIV.setOnClickListener(this);
        mBtnStartRec = findViewById(R.id.main_btn_startRec);
        mBtnStartRec.setOnClickListener(this);
        mBtnStopRec = findViewById(R.id.main_btn_stopRec);
        mBtnStopRec.setOnClickListener(this);
        mBtnTakPic = findViewById(R.id.main_btn_takepic);
        mBtnTakPic.setOnClickListener(this);
        mBtnCamera = findViewById(R.id.main_btn_camera);
        mBtnCamera.setOnClickListener(this);
        mBtnSoundRec = findViewById(R.id.main_btn_sound_rec);
        mBtnSoundRec.setOnClickListener(this);
        mBtnPreview = findViewById(R.id.main_btn_preview);
        mBtnPreview.setOnClickListener(this);
        findViewById(R.id.main_btn_audio).setOnClickListener(this);
        findViewById(R.id.main_btn_rec_list).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.main_btn_camera){
            onClickCamera();//开关相机
        }else if (id == R.id.main_btn_sound_rec){
            onClickSoundRec();//开关录音
        } else if (id == R.id.main_btn_takepic){
            isTakePic = true;//拍照
        }else if (id == R.id.main_btn_startRec){
            startRec();//开始录像
        }else if (id == R.id.main_btn_stopRec){
            stopRec(); //停止录像并播放
        } else if (id == R.id.main_btn_preview) {
            changePreview();
        } else if (id == R.id.main_img_pic){
            mPicIV.setVisibility(View.GONE);
        } else if (id == R.id.main_btn_audio){
            AudioActivity.startActivity(this);
        } else if (id == R.id.main_btn_rec_list){
            RecListActivity.startActivity(this);
        }
    }

    private void changePreview() {
        if (mSurfaceView.getVisibility() == View.GONE){
            mBtnPreview.setText("关闭预览");
            mSurfaceView.setVisibility(View.VISIBLE);
            mPreviewHelper = new CameraPreviewHelper();
            Size s = mCamera.getSize();
            mPreviewHelper.setPreview(mSurfaceView.getHolder().getSurface(),
                    s.getWidth(),s.getHeight(),true);

        }else{
            if (mPreviewHelper != null){
                mPreviewHelper.setPreview(null,0,0,true);
            }

            mBtnPreview.setText("开始预览");
            mSurfaceView.setVisibility(View.GONE);
        }
    }

    private void onClickSoundRec() {
        if (mSoundRec == null){
            try {
                mSoundRec = new XAudioRecord();
                mSoundRec.init(mContext,SOUND_SAMPLE,SOUND_CHANNEL,16,null);
                mSoundRec.start();
            }catch (Exception e){
                e.printStackTrace();
            }

            mBtnSoundRec.setText("结束录音");

            if (mHelper == null){
                mBtnStartRec.setEnabled(true);
            }
        }else{
            try {
                mSoundRec.stop();
            }catch (Exception e){
                e.printStackTrace();
            }
            mSoundRec = null;
            mBtnSoundRec.setText("开始录音");
            if (mSoundRec == null&&mCamera == null){
                mBtnStartRec.setEnabled(false);
            }
        }
    }

    private void onClickCamera() {
        if (mCamera == null){
            try {
                mCamera = initCamera();
                mCamera.start();
                mCamera.addListener(mImageAvailableListener);
            }catch (Exception e){
                e.printStackTrace();
            }

            mBtnCamera.setText("关闭摄像头");
            mBtnTakPic.setEnabled(true);
            mBtnPreview.setEnabled(true);
            if (mHelper == null){
                mBtnStartRec.setEnabled(true);
            }
        }else{
            try {
                mCamera.stop();
            }catch (Exception e){
                e.printStackTrace();
            }
            mCamera = null;

            mBtnCamera.setText("打开摄像头");
            mBtnTakPic.setEnabled(false);
            mBtnPreview.setEnabled(false);
            if (mSurfaceView.getVisibility() == View.VISIBLE){
                changePreview();
            }
            if (mSoundRec == null&&mCamera == null){
                mBtnStartRec.setEnabled(false);
            }
        }
    }

    public void startRec() {
        if (mCamera == null&&mSoundRec == null){
            Toast.makeText(mContext, "请先打开摄像头或录音",
                    Toast.LENGTH_SHORT).show();
            return;
        }

        if (mHelper == null){
            mBtnStartRec.setEnabled(false);
            mBtnStopRec.setEnabled(true);

            try {
                if (mCamera != null){
                    Size s = mCamera.getSize();
                    mVideoEncoder = new H264Encoder();
                    mVideoEncoder.init(mContext,s.getWidth(),
                            s.getHeight(),true,2*1024*1024);

                    mAudioEncoder =
                            new AMREncoder().init(mContext,
                                    SOUND_SAMPLE,SOUND_BITRATE,
                                    SOUND_CHANNEL,
                                    AMREncoder.AMR_TYPE_WB);
                    mSoundRec.setISoundRecListener(mSoundRecListener);
                }

                mHelper = new Mp4RecordHelper(mContext,mVideoEncoder,
                        mAudioEncoder);

                String videoPath =
                        mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES)+ File.separator+"recorder"+ SystemClock.uptimeMillis()+".mp4";
                mHelper.start(videoPath);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private void stopRec(){
        if (mHelper != null){
            String path = mHelper.closeAll();
            mHelper = null;
            VideoActivity.startActivity(mContext,path);
//            MP4PlayerActivity.startActivity(mContext,path,true);
        }else{
            Toast.makeText(mContext, "未录像", Toast.LENGTH_SHORT).show();
        }

        mBtnStartRec.setEnabled(true);
        mBtnStopRec.setEnabled(false);
    }

    private ICamera initCamera() throws Exception{
        boolean isScreenVertical =
                getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;

        CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        String[] cameraIds = manager.getCameraIdList();

        String cameraId = cameraIds[0];
        CameraCharacteristics mCameraCharacteristics =
                manager.getCameraCharacteristics(cameraId);

        int rotation = isScreenVertical?90:0;//竖屏录像需要旋转90°

        boolean isMirror =
                CameraCharacteristics.LENS_FACING_FRONT == mCameraCharacteristics.get(CameraCharacteristics.LENS_FACING);//前摄需要左右镜像

        StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

        Size[] sizes =
                map.getOutputSizes(SurfaceTexture.class);

        //从最高分辨率往后取，最大为1920*1080P
        int index = 0;
        for (int i = 0;i<sizes.length;i++){
            Size s = sizes[i];
            if (Math.max(s.getHeight(),s.getWidth()) <= 1920){
                index = i;
                break;
            }
        }
        Size size = sizes[index];

        ICamera videoEncoder = ICamera.build();
        videoEncoder.init(mContext,cameraId,size,rotation,isMirror);

        return videoEncoder;
    }
}
